package com.csap.framework.validation.factory;

import com.csap.framework.extension.result.ResultEnum;
import com.csap.framework.util.CollectionsUtil;
import com.csap.framework.util.FinalConfigParam;
import com.google.common.collect.Lists;
import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorDescriptor;
import org.hibernate.validator.internal.metadata.core.ConstraintHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.validation.Constraint;
import javax.validation.ConstraintValidator;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author yangchengfu
 * @description 方法过滤
 * @dataTime 2021年-01月-22日 18:52:00
 **/
public interface ValidateFilter extends ValidateData {
    /**
     * code键名称
     */
    String code = "code";
    /**
     * 消息键名称
     */
    String message = "message";

    Logger logs = LoggerFactory.getLogger(ValidateFilter.class);

    /**
     * 获取验证对象
     *
     * @return
     */
    ConstraintHelper getConstraintHelper();

    /**
     * 根据注解 获取验证业务处理类
     *
     * @param annotationType 字段注解
     * @param <A>            注解类型
     * @return
     */
    default <A extends Annotation> List<ConstraintValidatorDescriptor<A>> getAllValidatorDescriptors(Class<A> annotationType) {
        List<ConstraintValidatorDescriptor<A>> list = getConstraintHelper().getAllValidatorDescriptors(annotationType);
        if (CollectionsUtil.isEmpty(list)) {
            list = Lists.newArrayList();
        }
        return list;
    }

    /**
     * 获取当前字段所有验证逻辑
     *
     * @param fieldClass  字段class
     * @param annotations 注解
     * @return
     */
    default List<Validate.ConstraintValidatorField> getAllFieldConstraintValidator(Class fieldClass, Annotation[] annotations) {
        return Stream.of(annotations)
                .filter(i -> i.annotationType().isAnnotationPresent(Constraint.class))
                .map(i -> getAllValidatorDescriptors(i.annotationType())
                        .stream()
                        .map(i2 -> i2.getValidatorClass())
                        .filter(i2 -> containsClass(fieldClass, (Class) getClass(i2)))
                        .map(i3 -> validator(i3, i))
                        .collect(Collectors.toList()))
                .flatMap(Collection::stream)
                .filter(i -> containsClass(fieldClass, (Class) getClass(i.getValidator().getClass())))
                .collect(Collectors.toList());
    }

    /**
     * 获取验证的目标Class
     *
     * @param clss
     * @return
     */
    default Type getClass(Class<? extends ConstraintValidator> clss) {
        try {
            Type[] classes = clss.getGenericInterfaces();
            if (CollectionsUtil.isNotEmpty(classes)) {
                return ((ParameterizedType) classes[0]).getActualTypeArguments()[1];
            } else {
                return ((ParameterizedType) clss.getGenericSuperclass()).getActualTypeArguments()[0];
            }
        } catch (Exception e) {
            logs.error(e.getMessage(), e);
        }
        return null;
    }

    /**
     * 查找Class
     *
     * @param cl       具体对象 《子类》
     * @param contains 需要查找的对象《父类》
     * @return
     */
    default boolean containsClass(Class cl, Class contains) {
        if (cl == null) {
            return false;
        }
        if (FinalConfigParam.BASIC_DATA_TYPE_MAP.containsKey(cl.getName())) {
            cl = FinalConfigParam.BASIC_DATA_TYPE_MAP.get(cl.getName());
        }
        return contains.isAssignableFrom(cl);
    }

    /**
     * 获取具体验证规则
     *
     * @param cl
     * @param i
     * @return
     */
    default Validate.ConstraintValidatorField validator(Class<? extends ConstraintValidator> cl, Annotation i) {
        try {
            ConstraintValidator validator = cl.getDeclaredConstructor().newInstance();
            validator.initialize(i);
            return Validate.ConstraintValidatorField.builder()
                    .validator(validator)
                    .annotation(i)
                    .code(code(i))
                    .message(message(i))
                    .build();
        } catch (Exception e) {
            logs.error(e.getMessage(), e);
            return null;
        }
    }

    /**
     * 获取提示编码
     *
     * @param annotation
     * @return
     */
    default String code(Annotation annotation) {
        try {
            Method codeMethod = annotation.getClass().getMethod(code);
            if (codeMethod != null) {
                return codeMethod.invoke(annotation).toString();
            }
        } catch (Exception e) {
        }
        return ResultEnum.DATA_VALIDATE_ERROT.getCode();
    }

    /**
     * 获取消息提示
     *
     * @param annotation
     * @return
     */
    default String message(Annotation annotation) {
        try {
            Method codeMethod = annotation.getClass().getMethod(message);
            if (codeMethod != null) {
                return codeMethod.invoke(annotation).toString();
            }
        } catch (Exception e) {
        }
        return ResultEnum.DATA_VALIDATE_ERROT.getCode();
    }
}
